/*
 * restserver - A smart, efficient, low consumption RESTful application service platform writen in C
 * author	: calvin
 * email	: calvinwilliams@163.com
 *
 * Licensed under the Apache License v2.0, see the file LICENSE in base directory.
 */

#ifndef _H_RESTSERVER_API_
#define _H_RESTSERVER_API_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

/*
 * error code
 **/

#define RESTSERVER_MODULE_NO_FASTERHTTP				10
#define ASSEMBLE2_ERROR_CODE(_module_no_,_error_no_)	((_error_no_)>0?(_module_no_)*100+(_error_no_):(_module_no_)*-100-(_error_no_))

#define RESTSERVER_ERROR_URI_FIRST_CHARACTER			11
#define RESTSERVER_ERROR_TOO_MANY_HTTP_URI_PATHS		12
#define RESTSERVER_ERROR_URI_FIRST_CHARACTER_IN_CONFIG		13
#define RESTSERVER_ERROR_TOO_MANY_HTTP_URI_PATHS_IN_CONFIG	14
#define RESTSERVER_ERROR_RESTSERVICE_ENTRY_RETURN		15
#define RESTSERVER_ERROR_HTTP_DOMAIN				16
#define RESTSERVER_ERROR_PLACEHOLDER_LACK_OF_CLOSE		21
#define RESTSERVER_ERROR_BUFFER_OVERFLOW			22
#define RESTSERVER_ERROR_NO_ROUTE_IN_CONFIG			23
#define RESTSERVER_ERROR_SOMETHING				99

#define RESTSERVER_FATAL_CREATE_RESTSERVICECONTROLER		-11
#define RESTSERVER_FATAL_GET_RESTSERVICECONTROLER		-12
#define RESTSERVER_FATAL_ENV_VAR_NOT_FOUND			-3
#define RESTSERVER_FATAL_SOMETHING				-99

/*
 * application so module interfaces
 **/

struct RestServerContext;

typedef int funcInitRestApplication( struct RestServerContext *ctx );
typedef int funcCallRestApplication( struct RestServerContext *ctx );
typedef int funcCleanRestApplication( struct RestServerContext *ctx );

/*
 * util
 **/

#define STRNCMPSTRN(_str1_,_str1_len_,_cmp_,_str2_,_str2_len_)	( (_str1_len_) _cmp_ (_str2_len_) && STRNCMP( (_str1_) , _cmp_ , (_str2_) , (_str2_len_) ) )
#define STRNCMPSTR(_str1_,_str1_len_,_cmp_,_str2_)		STRNCMPSTRN( (_str1_) , (_str1_len_) , _cmp_ , (_str2_) , (strlen(_str2_)) )
#define STRNCMPRSTR(_str1_,_str1_len_,_cmp_,_literal_str2_)	STRNCMPSTRN( (_str1_) , (_str1_len_) , _cmp_ , (_literal_str2_) , (sizeof(_literal_str2_)-1) )

#ifndef HTTP_RETURN_NEWLINE
#define HTTP_RETURN_NEWLINE	"\r\n"
#endif

#define HTML_NEWLINE		"<br />"
#define HTML_RETURN_NEWLINE	"<p />"

#define BUFNPRINTF(_buf_base_,_buf_size_,_str_len_,_format_,...)	\
	{ \
		int	len ; \
		len = snprintf( (_buf_base_)+(_str_len_) , (_buf_size_) , (_format_) , __VA_ARGS__ ) ; \
		if( len > 0 ) \
			(_str_len_) += len ; \
	} \

#define BUFPRINTF(_buf_base_,_str_len_,_format_,...)		BUFNPRINTF(_buf_base_,sizeof(_buf_base_),_str_len_,_format_,__VA_ARGS__)

#define BUFNSTRCAT(_buf_base_,_buf_size_,_str_len_,_cat_str_)	\
	{ \
		int	len ; \
		len = snprintf( (_buf_base_)+(_str_len_) , (_buf_size_) , (_cat_str_) ) ; \
		if( len > 0 ) \
			(_str_len_) += len ; \
	} \

#define BUFSTRCAT(_buf_base_,_str_len_,_cat_str_)		BUFNSTRCAT(_buf_base_,sizeof(_buf_base_),_str_len_,_cat_str_)

/*
 * rest server context
 **/

struct HttpEnv ;

struct HttpEnv *RSAPIGetHttpEnv( struct RestServerContext *ctx );

char *RSAPIGetHttpMethodPtr( struct RestServerContext *ctx , int *p_method_len );
char *RSAPIGetHttpUriPtr( struct RestServerContext *ctx , int *p_uri_len );

int RSAPIGetHttpUriPathsCount( struct RestServerContext *ctx );
char *RSAPIGetHttpUriPathPtr( struct RestServerContext *ctx , int index , int *p_path_len );
int RSAPIGetHttpUriQueriesCount( struct RestServerContext *ctx );
char *RSAPIGetHttpUriQueryKeyPtr( struct RestServerContext *ctx , int index , int *p_key_len );
char *RSAPIGetHttpUriQueryValuePtr( struct RestServerContext *ctx , int index , int *p_value_len );

char *RSAPIGetHttpRequestBodyPtr( struct RestServerContext *ctx , int *p_body_len );

void RSAPISetUserData( struct RestServerContext *ctx , void *user_data );
void *RSAPIGetUserData( struct RestServerContext *ctx );

int RSAPIFormatHttpResponse( struct RestServerContext *ctx , char *http_response_body , int http_response_body_len , char *http_header_format , ... );

/*
 * uri controler
 **/

typedef int funcRestServiceEntry( struct RestServerContext *ctx );

/*
/a/{}/b
*/

#define HTTP_METHOD_MAX_LEN		8
#define HTTP_URI_PATHS_MATCH_MAX_LEN	256

struct RestServiceConfig
{
	char			http_method[ HTTP_METHOD_MAX_LEN+1 ] ;
	char			http_uri_paths_match[ HTTP_URI_PATHS_MATCH_MAX_LEN+1 ] ;
	funcRestServiceEntry	*pfuncRestServiceEntry ;
} ;

struct RestServiceControler;

struct RestServiceControler *RSAPICreateRestServiceControler( struct RestServiceConfig *config_array );
int RSAPIDispatchRestServiceControler( struct RestServiceControler *ctl , struct RestServerContext *ctx );
void RSAPIDestroyRestServiceControler( struct RestServiceControler *ctl );

#endif

